// File: jmcomic-core/src/main/java/dev/jukomu/common/base/mapper/Mapper.java
package dev.jukomu.common.base.mapper;

import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

/**
 * 对应Python的Mapper，定义了键值对映射的通用接口。
 *
 * @param <K> 键的类型
 * @param <V> 值的类型
 */
public interface Mapper<K, V> extends Iterable<Map.Entry<K, V>> {

    /**
     * 设置键值对。
     *
     * @param key   键
     * @param value 值
     * @param save  是否立即保存到持久化存储
     * @throws IOException 如果保存失败
     */
    void set(K key, V value, boolean save) throws IOException;

    /**
     * 设置键值对。
     *
     * @param key   键
     * @param value 值
     * @throws IOException 如果保存失败
     */
    default void set(K key, V value) throws IOException {
        set(key, value, false);
    }

    /**
     * 获取指定键的值。
     *
     * @param key          键
     * @param defaultValue 默认值，如果键不存在则返回此值
     * @return 键对应的值，或默认值
     */
    V get(K key, V defaultValue);

    /**
     * 获取指定键的值。
     *
     * @param key 键
     * @return 键对应的值，如果键不存在则返回null
     */
    default V get(K key) {
        return get(key, null);
    }

    /**
     * 检查是否不包含指定键。
     *
     * @param key 键
     * @return 如果不包含返回 true
     */
    default boolean hasNotKey(K key) {
        return !containsKey(key);
    }

    /**
     * 移除指定键值对。
     *
     * @param key  键
     * @param save 是否立即保存到持久化存储
     * @throws IOException 如果保存失败
     */
    void remove(K key, boolean save) throws IOException;

    /**
     * 移除指定键值对。
     *
     * @param key 键
     * @throws IOException 如果保存失败
     */
    default void remove(K key) throws IOException {
        remove(key, false);
    }

    /**
     * 获取映射中键值对的数量。
     *
     * @return 数量
     */
    int size();

    /**
     * 设置内部数据Map。
     *
     * @param data 新的Map数据
     */
    void setData(Map<K, V> data);

    /**
     * 获取内部数据Map。
     *
     * @return 内部数据Map
     */
    Map<K, V> getData();

    /**
     * 清空映射数据。
     */
    void clearData();

    /**
     * 从持久化存储加载数据。
     *
     * @throws IOException 如果加载失败
     */
    void load() throws IOException;

    /**
     * 保存数据到持久化存储。
     *
     * @param callback 保存前的回调函数，可以对数据进行处理
     * @return 保存后的数据（通常为Map或List）
     * @throws IOException 如果保存失败
     */
    Object save(Function<Map<K, V>, Object> callback) throws IOException;

    /**
     * 保存数据到持久化存储。
     *
     * @throws IOException 如果保存失败
     */
    default void save() throws IOException {
        save(null);
    }

    /**
     * 确保数据已加载。
     *
     * @throws IOException 如果加载失败
     */
    void makeSureLoaded() throws IOException;

    /**
     * 获取所有键值对的Set。
     *
     * @return Entry Set
     */
    Set<Map.Entry<K, V>> entrySet();

    /**
     * 获取所有键的Set。
     *
     * @return Key Set
     */
    Set<K> keySet();

    /**
     * 获取所有值的Collection。
     *
     * @return Values Collection
     */
    Collection<V> values();

    /**
     * 检查是否包含指定键。
     *
     * @param key 键
     * @return 如果包含返回 true
     */
    boolean containsKey(K key);

    // 对应Python的 __getitem__ 和 __setitem__，在Java中通过 get/set 方法和 Map 接口实现
    // public V get(K key) throws java.util.NoSuchElementException {
    //     V obj = get(key, null);
    //     if (obj == null) {
    //         throw new java.util.NoSuchElementException("Key not found: " + key);
    //     }
    //     return obj;
    // }
    // public void set(K key, V value) throws IOException;

    /**
     * 获取映射中键值对的数量。
     *
     * @return 数量
     */
    default int count() {
        return size();
    }
}